/*
 * cJugador.cpp
 *
 *  Created on: Nov 2, 2014
 *      Author: root
 */

#include "cJugador.h"
#include "../objetosGrilla.h"
#include "../manejadorGrilla.h"
#include "../clasesAuxiliares/SocketCommunication.h"
#include "../clasesAuxiliares/envioAlCliente.h"
#include <iostream>

#include <stdio.h>

const int GRILLA_WIDTH = 64;
const int GRILLA_HEIGHT= 48;


const int SALTO_ARRIBA = 5;
const int SALTO_IZQUIERDA = 6;
const int SALTO_DERECHA = 7;

const int TIPO_ESCALERA_REAL = 1;
const int TIPO_ESCALERA_FALSA= 2;


cJugador::~cJugador() {

}

cJugador::cJugador(int playerNumber) {
	this->height = 3;
	this->witdh = 2;
	this->rescates = 0;
	this->vidas = 3;
	this->tipoEscalera =0;
	this->estaCayendo = false;
	this->estaSubiendo = false;
	this->estaSaltando = false;
	this->SaltandoDireccion = 0;
	this->saltoMovimiento = 0;
	//ENVIAR CANTIAD DE VIDAS
	this->playerNumber = playerNumber;
	int typeJugador ;
	if(this->playerNumber == 1)
	{
		sprintf(this->cId,"jug_1");
		typeJugador = objetosGrilla::getTypeJugador1();
	}
	else
	{
		sprintf(this->cId,"jug_2");
		typeJugador = objetosGrilla::getTypeJugador2();

	}
	this->type = typeJugador;

}


void cJugador::mover(manejadorGrilla &grilla)
{
	//verifico siempre si esta saltando
	if(this->estaSaltando == true)
		this->checkSaltando(grilla);

	if(this->estaCayendo == true)
		this->checkCayendo(grilla);

}

void cJugador::inicializar(SocketCommunication *socket_J1, SocketCommunication *socket_J2)
{
	//sprintf(this->cId, "JUG_%d_%d", playerNumber, id);
	this->socket_J1 = socket_J1;
	this->socket_J2 = socket_J2;
	this->estaCayendo = false;
	this->estaSubiendo = false;
	this->estaSaltando = false;
	this->tipoEscalera = 0;
	this->SaltandoDireccion = 0;
	this->saltoMovimiento = 0;
	if(this->playerNumber == 1)
	{
		this->x = 2;
		this->y = 42;
	}
	else
	{
		this->x = 60;
		this->y = 42;

	}
	envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
}


void cJugador::moverIzquierda( manejadorGrilla &grilla)
{
	//evaluo que no sea el fin de la pantalla en x
	if(this->x - 1 < 0) {return;}

	//si estoy cayendo (no hay piso muevo el jugador para abajo)
	if(this->estaCayendo == true){return;}

	//si estoy cayendo (no hay piso muevo el jugador para abajo)
	if(this->estaSubiendo == true){return;}

	//si estoy cayendo (no hay piso muevo el jugador para abajo)
	if(this->estaSaltando == true){return;}

	//asigno nuevamente las variables
	this->x = this->x -1;
	envioAlCliente::envioPosicion(this->cId, socket_J1,socket_J2,this->x,this->y);
	//std::cout << this->cId << "I: (" << this->x << " , " << this->y << ")" << std::endl;

	int x0 =  this->x;
	int xF =  this->x + this->witdh - 1;
	int yF = this->y + this->height - 1;

	if(this->estaSaltando == false && grilla.matriz[x0][yF+1]  == 0 && grilla.matriz[xF][yF+1] == 0){
		this->estaCayendo = true;
	}
}


void cJugador::moverDerecha( manejadorGrilla &grilla)
{
	int x0 =  this->x;
	int y0 = this->y;

	int xF =  this->x + this->witdh - 1;
	int yF = this->y + this->height - 1;

	//evaluo que no sea el fin de la pantalla en x
	if(xF + 1 > GRILLA_WIDTH -1) {return;}

	//si estoy cayendo (no hay piso muevo el jugador para abajo)
	if(this->estaCayendo == true){return;}

	//si estoy cayendo (no hay piso muevo el jugador para abajo)
	if(this->estaSubiendo == true){return;}

	//si estoy cayendo (no hay piso muevo el jugador para abajo)
	if(this->estaSaltando == true){return;}

	//muevo
	this->x = this->x + 1;
	envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
	//std::cout << this->cId << "D: (" << this->x << " , " << this->y << ")" << std::endl;

	x0 =  this->x;
	xF =  this->x + this->witdh - 1;

	if(this->estaSaltando == false && grilla.matriz[x0][yF+1] == 0 && grilla.matriz[xF][yF+1] == 0)
	{
		this->estaCayendo = true;
	}
}


void cJugador::MoverArribaEscalera(manejadorGrilla &grilla)
{
	if(this->estaSaltando == true){return;}
	if(this->estaCayendo == true){return;}

	//si no hay escalera arriba sale
	//if (grilla.matriz[this->x][this->y - 1] == 0 ||  grilla.matriz[this->x + 1][this->y - 1] == 0 )
	//	return;

	int tipoEscalera = 0;
	if(this->estaSubiendo ==  false)
	{
		//evaluo si el jugador esta alineado con la escalera
		if((grilla.matriz[this->x][this->y - 1] == objetosGrilla::getTypeEscalera() && grilla.matriz[this->x + 1][this->y - 1] == objetosGrilla::getTypeEscalera()) || (grilla.matriz[this->x][this->y - 1] == objetosGrilla::getTypeEscaleraFalsa() && grilla.matriz[this->x + 1][this->y - 1] == objetosGrilla::getTypeEscaleraFalsa()))
		{
			this->estaSubiendo = true;
			if(grilla.matriz[this->x][this->y - 1] == objetosGrilla::getTypeEscalera())
				this->tipoEscalera = TIPO_ESCALERA_REAL;
			else
				this->tipoEscalera = TIPO_ESCALERA_FALSA;
		}
	}

	if(this->estaSubiendo == true)
	{
		//obtengo el tipo de escalera a subir
		if(this->tipoEscalera == TIPO_ESCALERA_REAL)
			this->subirEscaleraReal(grilla);
		else
			if(this->tipoEscalera == TIPO_ESCALERA_FALSA)
				this->subirEscaleraFalsa(grilla);
	}
}


void cJugador::subirEscaleraReal(manejadorGrilla &grilla)
{
//	// Partimos de la base que todas las escaleras tienen 5 unidades de alto + 1 del piso...
//	int cantidadEscalones = 0;
//	int aux = this->height;
//	//obtengo en el escalon que estoy en la escalera
//	while(grilla.matriz[this->x][this->y + aux] != objetosGrilla::getTypePiso())
//	{
//		cantidadEscalones++;
//		aux++;
//	}
//
//	std::cout << "subirEscaleraReal - CANITAD ESCALONES: " << cantidadEscalones << std::endl;

	this->y--;
	envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
	//std::cout << this->cId << "SUBIR REAL CANITAD ESCALOONES: (" << cantidadEscalones << std::endl;

	if(grilla.matriz[this->x][this->y + 2] == 0)
	{
		this->estaSubiendo = false;
		this->tipoEscalera = 0;
	}
}


void cJugador::subirEscaleraFalsa(manejadorGrilla &grilla)
{

//	int cantidadEscalones = 0;
//	int aux = this->height;
//	//obtengo en el escalon que estoy en la escalera
//	while(grilla.matriz[this->x][this->y + aux] != objetosGrilla::getTypePiso())
//	{
//		cantidadEscalones++;
//		aux++;
//	}
//
//	std::cout << "subirEscaleraFalsa - CANITAD ESCALONES: " << cantidadEscalones << std::endl;

	//si esta en el primer escalon no hago nada
	if(grilla.matriz[this->x][this->y + 3] == objetosGrilla::getTypePiso())
	{
		this->y-- ;
		envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
		////std::cout << this->cId << "S_F: (" << this->x << " , " << this->y << ")" << std::endl;
	}

}


void cJugador::MoverAbajoEscalera(manejadorGrilla &grilla)
{
	if(this->estaSaltando == true){return;}
	if(this->estaCayendo == true){return;}

	//evaluo si efectivamente puedo bajar la escalera...
	//las escaleras falsas no se pueden bajar...
	if((this->estaSubiendo == false) && (grilla.matriz[x][y+4] == objetosGrilla::getTypeEscalera() && grilla.matriz[x+1][y+4] == objetosGrilla::getTypeEscalera()))
	{
		this->estaSubiendo =  true;
		this->tipoEscalera =  TIPO_ESCALERA_REAL;
	}

	if(this->estaSubiendo == true)
	{
		this->y++;
		envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
		if(grilla.matriz[this->x][this->y + 3] == objetosGrilla::getTypePiso())
		{
			this->estaSubiendo = false;
			this->tipoEscalera = 0;
		}
	}
}

void cJugador::Saltar(manejadorGrilla &grilla)
{
	if(this->estaCayendo == true){return;}
	if(this->estaSubiendo == true){return;}
	if(this->estaSaltando == true){return;}

	this->estaSaltando = true;
	this->saltoMovimiento = 1;
}

void cJugador::SaltarArriba(manejadorGrilla &grilla)
{
	if(this->estaCayendo == true){return;}
	if(this->estaSubiendo == true){return;}
	if(this->estaSaltando == true){return;}

	this->estaSaltando = true;
	this->SaltandoDireccion = SALTO_ARRIBA;
	this->saltoMovimiento = 1;
}

void cJugador::SaltarIzquierda(manejadorGrilla &grilla)
{
	if(this->estaCayendo == true){return;}
	if(this->estaSubiendo == true){return;}
	if(this->estaSaltando == true){return;}

	this->estaSaltando = true;
	this->SaltandoDireccion = SALTO_IZQUIERDA;
	this->saltoMovimiento = 1;
}

void cJugador::SaltarDerecha(manejadorGrilla &grilla)
{
	if(this->estaCayendo == true){return;}
	if(this->estaSubiendo == true){return;}
	if(this->estaSaltando == true){return;}

	this->estaSaltando = true;
	this->SaltandoDireccion = SALTO_DERECHA;
	this->saltoMovimiento = 1;
}

//esta funcion la tengo que usar siempre en la sincronizacion que es la que termina caer el personaje...
void cJugador::checkCayendo(manejadorGrilla &grilla)
{
	if(grilla.matriz[this->x][this->y + 4] == objetosGrilla::getTypePiso())
		this->y = this->y + 1;
	else
		this->y = this->y + 2;
	envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
	if(grilla.matriz[this->x][this->y + 3] == objetosGrilla::getTypePiso())
	{
		this->estaCayendo =  false;
	}
}


//esta funcion la tengo que usar siempre en la sincronizacion que es la que termina de realizar el salto...
void cJugador::checkSaltando(manejadorGrilla &grilla)
{

	if(this->SaltandoDireccion == SALTO_DERECHA)
	{
		if(this->x + 2 < 64)
			this->x++;
	}
	else
	{
		if(this->SaltandoDireccion == SALTO_IZQUIERDA)
		{
			if(this->x > 0)
				this->x--;
		}
	}

	if(this->saltoMovimiento > 0 && this->saltoMovimiento <= 3)
		this->y--;
	else
		if(this->saltoMovimiento >=6 && this->saltoMovimiento <= 8)
			this->y++;

	envioAlCliente::envioPosicion(this->cId ,socket_J1,socket_J2,this->x,this->y);
	//std::cout << this->cId << "SALTO: (" << this->x << " , " << this->y << ")" << std::endl;

	this->saltoMovimiento++;
	if(this->saltoMovimiento == 9)
	{
		this->saltoMovimiento = 0;
		this->estaSaltando = false;
		this->SaltandoDireccion = 0;
		if(grilla.matriz[this->x][this->y + this->height] == 0 && grilla.matriz[this->x+1][this->y + this->height] == 0)
		{
			this->estaCayendo = true;
		}
	}

}


